iT邦幫忙

2023 iThome 鐵人賽

DAY 5
1
Software Development

玩轉 Python 與 MongoDB系列 第 5

玩轉 Python 與 MongoDB_Day05_GridFS 大型資料 & 檔案插入

  • 分享至 

  • xImage
  •  

在 MongoDB 當中,有著每個 Document 的大小最大為 16 MB 的限制,如果今天你想插入的資料超過 16 MB,MonGODB 提供了 GridFS API 來協助你內容進行切割,同時他也可以針對各種檔案進行儲存,今天會分別使用存入 json 格式以及儲存圖片的方式帶大家了解 GridFS 的操作

一、GridFS 對 JSON 的寫入與讀取

(一)、寫入

JSON 格式是我們最常用來存放在 mongodb 裡面的資料格式,但 GridFS 只接收字串以及檔案類型的參數,因此在寫入 JSON 或是 dictionary 等型態的資料時,我們必須先透過 json 套件將資料轉換成字串,接著再寫入,下方附上範例

import os
import json
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient

# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))

# 讀取 datas 目錄下的 1 月份資料
file = BASE_DIR / "datas" / "臺中市111年1月10大易肇事路口.json"

# 設定連線資訊
# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")

# 建立 GridFS 物件
gridfs = GridFS(database=database)

with open(file=file, encoding="utf-8") as f:
    # 讀取 json 檔案的內容
    datas = json.load(fp=f)

    # 將 dictionary 轉換成字串,並指定字串編碼
    string_datas = json.dumps(datas).encode("utf-8")

    # 進行寫入
    inserted_id = gridfs.put(data=string_datas)
    print(inserted_id)

client.close()

下方圖片中我們可以看到成功插入後印出的 inserted_id

插入 json 成功截圖

下方圖片中午們可以透過 Mongo Compass 看到 GridFS 自動幫我們建立了兩個 collection

自動創建 collection 截圖

(二)、讀取

我們可以透過 GridFS.get() 並搭配 id 來取得被切割的檔案,由於檔案經過切割,需要使用檔案的時候要將回傳的資料透過迴圈進行跌代重組才可以進行使用

GridFS 會協助將存放的內容已 binary 的形式進行切割,因此若存放的資料為字串讀回來時須作相對應的 decode 動作

import os
import json
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
from bson.objectid import ObjectId

# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))

# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")

# 建立 GridFS 物件
gridfs = GridFS(database=database)

# 透過 id 取得所有被切割的檔案,記得 id 要使用 bson.object_id.ObjectId
chunks = gridfs.get(file_id=ObjectId("646389db4f978885e6985b93"))

# 將 chunks 進行重組
result = b""
for chunk in chunks:
    result += chunk

print(json.loads(result.decode("utf8")))

client.close()

下圖為查詢成功範例

查詢 json 成功截圖

二、GridFS 對檔案的寫入與讀取

(一)、寫入

基本上和 json 格式寫入的方式相差不大,但要注意的是開啟檔案的時候要記得使用 "rb" 模式,也就是 read binary 的意思

import os
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient

# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))

# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")

# 建立 GridFS 物件
gridfs = GridFS(database=database)

with open(file="範例圖片.png", mode="rb") as file:
    inserted_id = gridfs.put(data=file)
    print(inserted_id)

client.close()

下圖為插入檔案成功截圖

插入 file 成功截圖

(二)、讀取

同樣的,這邊也需要使用 "wb" 來表示要進行 write binary 的動作,同時賦予新的檔案新的名稱

注意:若要存放檔案必須有一個對應的 collection 來存放檔案名稱、副檔名以及插入後所產生的 id,此為最理想的應用情況

import os
from pathlib import Path
from dotenv import load_dotenv
from pymongo.database import Database
from gridfs import GridFS
from pymongo.mongo_client import MongoClient
from bson.objectid import ObjectId

# 讀取 .env 取得連線資訊
BASE_DIR = Path(__file__).parent.parent
load_dotenv(str(BASE_DIR / ".env"))

# 建立 client 並與 db 進行連線
client = MongoClient(host=os.getenv("MONGODB_ATLAS_URL"))
database = Database(client=client, name="2023_ithelp")

# 建立 GridFS 物件
gridfs = GridFS(database=database)

# 透過 id 取得所有被切割的檔案,記得 id 要使用 bson.object_id.ObjectId
chunks = gridfs.get(file_id=ObjectId("64638f1de59d60a299db3c72"))

# 將 chunks 進行重組
result = b""
for chunk in chunks:
    result += chunk

with open("讀取後的圖片.png", "wb") as file:
    file.write(result)

client.close()

下圖為讀取檔案並寫入成功的截圖

讀取 file 成功截圖


上一篇
玩轉 Python 與 MongoDB_Day04_資料插入
下一篇
玩轉 Python 與 MongoDB_Day06_Pydantic 基本介紹
系列文
玩轉 Python 與 MongoDB30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言